import logging
import asyncio
import uvicorn
import argparse
import socket
import sys
from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends

# 导入统一的日志配置模块
from log_config import setup_logging, shutdown_logging

# 导入新的依赖注入容器
from services.dependency_container import get_container, register_services, shutdown_container

# 导入路由模块
from api.main_routes import register_main_routes
from api.category_routes import register_category_routes
from api.query_routes import register_query_routes
from api.embed_routes import register_embed_routes

# 导入异常处理中间件
from utils.exception_handlers import setup_exception_handlers

# 配置日志
setup_logging()
logger = logging.getLogger(__name__)

# 定义依赖项：获取EmbeddingService实例
def get_embedding_service():
    try:
        container = get_container()
        return container.get('embedding_service')
    except KeyError as e:
        raise RuntimeError("EmbeddingService 尚未初始化") from e

# 定义依赖项：获取线程池
def get_thread_pool():
    try:
        container = get_container()
        return container.get('thread_pool')
    except KeyError as e:
        raise RuntimeError("线程池尚未初始化") from e

# 定义依赖项：获取配置服务
def get_config_service():
    try:
        container = get_container()
        return container.get('config_service')
    except KeyError as e:
        raise RuntimeError("配置服务尚未初始化") from e

@asynccontextmanager
async def lifespan(app):  
    # 应用启动时执行的代码
    logger.info("进入 asynccontextmanager lifespan() ")
    
    # 使用新的依赖注入容器注册和初始化所有服务
    register_services()
    
    # 设置异常处理中间件
    setup_exception_handlers(app)
    
    # 注册路由
    register_main_routes(app, get_config_service())
    register_category_routes(app, get_embedding_service, get_thread_pool)
    register_query_routes(app, get_embedding_service, get_thread_pool, get_config_service)
    register_embed_routes(app, get_embedding_service, get_thread_pool)

    yield

    logger.info("开始退出 asynccontextmanager lifespan() ")

    # 应用关闭时执行的代码
    shutdown_container()
    
    # 关闭日志处理器
    shutdown_logging()

# 创建FastAPI应用
app = FastAPI(
    title="信息服务", 
    description="提供信息保存和检索",
    lifespan=lifespan
)

if __name__ == "__main__":
    # 解析命令行参数
    parser = argparse.ArgumentParser(description='信息服务')
    parser.add_argument('--port', type=int, help='Web服务器监听端口')
    args = parser.parse_args()
    
    # 使用新的依赖注入容器注册和初始化服务以获取配置
    register_services()
    container = get_container()
    
    # 获取配置服务来读取端口配置
    config_service = container.get('config_service')
    webserver_config = config_service.get_webserver_config()
    
    # 如果命令行提供了端口参数，则使用它，否则使用配置文件中的端口
    port = args.port if args.port else webserver_config['port']
    logger.info(f"WebServer启动服务, 端口: {port}")
    
    # 检查端口是否被占用
    def check_port_in_use(host='0.0.0.0', port_to_check=port):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            try:
                s.bind((host, port_to_check))
                return False
            except socket.error as e:
                return True
            finally:
                s.close()
    
    # 如果端口已被占用，提示并退出
    if check_port_in_use(port_to_check=port):
        logger.error(f"错误: 端口 {port} 已被占用，请释放该端口或使用其他端口。")
        sys.exit(1)
    
    # 注意：在uvicorn运行时，lifespan会再次调用register_services()
    uvicorn.run(app, host="0.0.0.0", port=port)
